#include "typeface.h"

#include <hb.h>

#include "cmap_parser.h"

Typeface::Typeface(SkTypeface *tf) : Typeface(sk_sp<SkTypeface>(tf))
{
}

Typeface::Typeface(sk_sp<SkTypeface> tf)
    : typeface_(tf)
{
    if (typeface_ != nullptr) {
        typeface_->getPostScriptName(&name_);
    }
}

Typeface::~Typeface()
{
    if (hblob_ != nullptr) {
        hb_blob_destroy(hblob_);
    }
}

std::string Typeface::GetPostScriptName()
{
    return name_.c_str();
}

bool Typeface::Has(uint32_t ch)
{
    if (!isCmapInited) {
        if (InitCmap()) {
            return false;
        }
        isCmapInited = true;
    }

    if (!isCmapParsed) {
        if (ParseCmap()) {
            return false;
        }
        isCmapParsed = true;
    }

    return ranges_.Has(ch);
}

int Typeface::InitCmap()
{
    auto tag = HB_TAG('c', 'm', 'a', 'p');
    auto size = typeface_->getTableSize(tag);
    if (size == 0) {
        printf("%s haven't cmap\n", name_.c_str());
        return -1;
    }

    auto data = malloc(size);
    auto retv = typeface_->getTableData(tag, 0, size, data);
    if (size != retv) {
        printf("falied %d\n", __LINE__);
        free(data);
        return -1;
    }

    hblob_ = hb_blob_create(reinterpret_cast<const char *>(data),
                            size, HB_MEMORY_MODE_WRITABLE, data, free);
    return 0;
}

int Typeface::ParseCmap()
{
    CmapParser parser(hb_blob_get_data(hblob_, nullptr), hb_blob_get_length(hblob_));
    return parser.Parse(ranges_);
}
